# {{= d.name }}

---

{{= d.name }}

## 框架

1. `WEB` 框架: [Sanic](https://sanic.dev/zh/guide/how-to/orm.html#sqlalchemy)
2. `Mysql ORM` 框架: [Tortoise ORM](https://tortoise.github.io/)
3. `HTTP` 框架: [httpx](https://www.python-httpx.org/)

## 启动

### 1. 启动 `WEB` 服务器

运行 `python app.py` 启动 `WEB` 服务器, 默认支持热重载。

### 2. 测试服务器启动

服务器启动后, 可以通过浏览器访问 `http://127.0.0.1:3002/{{= d.name }}/system_monitor` 来验证服务器是否启动成功。

## 签名

### 1. 将 `app_id` 分配的账号、`timestamp` 请求时间戳, 精确到秒(10 位)、`nonce_str` 生成的随机字符串 加入请求中

### 2. 对请求参数按 `key` 的字典排序

### 3. 将请求参数按排序后组装为请求字符串

### 4. 再请求字符串的末尾添加 `&key=xx` 其中 `key` 为分配的 `app_secret`

### 5. 对请求字符串进行 `md5` 后大写即最终的签名

```javascript
const url = "/x?a=1&b=2"; // 请求url

const args = { a: "1", b: "2" }; // 请求参数
// 1. 请求中加入 app_id、timestamp、nonce_str
args = { app_id: "xxx", timestamp: 137682032, nonce_str: "xxxx", a: "1", b: 2 };

// 按键的字典排序
const keys = Object.keys(args).sort();

// 转成键值对
let paramPair = [];
for (let i = 0, len = keys.length; i < len; i++) {
  let k = keys[i];
  paramPair.push(k + "=" + param[k]); // urlencode 编码
}

// 最后加上 key
paramPair.push("key=" + key);

// 拼接
let stringSignTemp = paramPair.join("&");

let sign = CryptoJS.MD5(stringSignTemp).toString().toUpperCase();
```

> 注意事项:
>
> 1. 只有值是字符串、数字、布尔类型的才参与签名

## 部署

### 1. 进入 `docker compose` 配置目录停止容器

```shell
docker compose stop {{= d.name }}

docker compose rm -f
```

### 2. 进入项目目录(`/projects/{{= d.name }}`)拉取最新代码并重新构建镜像

```shell
cd /projects/{{= d.name }}

git pull origin master:master

docker rmi -f {{= d.name }}

docker build -t {{= d.name }}
```

### 3. 重新进入 `docker compose` 目录并重启服务

```shell
cd /projects/{{= d.name }}/docker-compose

docker compose up {{= d.name }} -d
```
